package monitor

import (
	"fmt"
	"html/template"
	"net/http"
	"time"
)
import (
	"code.google.com/p/gcfg"
)
import (
	"monitor/alert"
	"r_log"
	"recom"
)

type MConf struct {
	IP              string
	Port            int
	CommandAddr     string
	DetailStateAddr string
	StateAddr       string
	StatisticAddr   string
	HomePageAddr    string
}

type AConf struct {
	ServerIp   string
	ServerPort uint32
	Interval   time.Duration //单位：秒
	ModuleName string
	PointName  string
}

// ======================================================================
// 用于首页显示基本信息
func (a *AConf) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// todo must处理错误是否要用 会产生panic返回给上层
	t := template.Must(template.ParseFiles(monitorunit.MonitorConf.HomePageAddr))
	err := t.Execute(w, a)
	if err != nil {
		r_log.Logger.Warn("Home Page template execute is faild: %v", err)
	}
}

// state的概览与详细信息可扩展结构
type StateInfo struct {
	StateOverview // State 四个周期的概览
	SpecificState // State四个周期的详细信息
}

type Monitor struct {
	Commands     Command
	MonitorConf  MConf
	AlertConf    AConf
	Recommender  *recom.Recommender
	GetState     StateInfo // state页面需要的信息
	GetStatistic StatisticInfo
}

var monitorunit Monitor

func StartMonitor(confPath string, r *recom.Recommender) error {
	monitorunit.Recommender = r
	if err := gcfg.ReadFileInto(&monitorunit, confPath); err != nil {
		return fmt.Errorf("gcfg.ReadFileInto(): %s", err.Error())
	}
	StartAlertMonitor(r)
	http.Handle("/", &monitorunit.AlertConf)
	http.Handle("/State", &monitorunit.GetState.StateOverview)
	http.Handle("/State/period", &monitorunit.GetState.SpecificState)
	//http.Handle("/Statistic", &monitorunit.GetStatistic)
	//http.Handle("/Command", &monitorunit.Commands)

	go func() {
		err := http.ListenAndServe(fmt.Sprintf("%v:%v", monitorunit.MonitorConf.IP, monitorunit.MonitorConf.Port), nil)
		if err != nil {
			r_log.Logger.Warn("Monitor start faild: %v", err)
		}
	}()
	return nil
}

func StartAlertMonitor(r *recom.Recommender) {
	s := alert.NewItem(monitorunit.AlertConf.ServerIp, monitorunit.AlertConf.ServerPort, monitorunit.AlertConf.ModuleName, monitorunit.AlertConf.PointName)
	go func() {
		for {
			if r.Bcs.DdsSocket.ConnectCount > 0 {
				s.SetOK()
			} else {
				s.SetErr()
			}
			if err := s.Send(); err != nil {
				r_log.Logger.Error("Send dds start to alert server faild! %v", err)
			}
			time.Sleep(time.Second * monitorunit.AlertConf.Interval)
		}
	}()

}
